package com.ecoolex.ying.space.core.manager;

import com.alibaba.fastjson.JSON;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.ying.space.core.dao.GoodsDAO;
import com.ecoolex.ying.space.core.service.PickGoodsSearchService;
import com.ecoolex.ying.space.entity.Goods;
import com.ecoolex.ying.space.entity.GoodsExample;
import com.ecoolex.ying.space.entity.GoodsWithBLOBs;
import com.ecoolex.ying.space.entity.GoodsWithBLOBs.Column;
import com.ecoolex.ying.space.enums.GoodsStatus;
import com.ecoolex.ying.space.pojo.EditGoodsDTO;
import com.ecoolex.ying.space.pojo.QueryGoodsDTO;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.Date;
import java.util.List;

@Service
public class GoodsManager {
    @Autowired
    private GoodsDAO dao;
    @Autowired
    private PickGoodsManager pickGoodsManager;
    @Autowired
    private GoodsAttachmentManager goodsAttachmentManager;
    @Autowired
    private GoodsSpecGroupManager goodsSpecGroupManager;
    @Autowired
    private GoodsSpecManager goodsSpecManager;
    @Autowired
    private GoodsProductManager goodsProductManager;
    @Autowired
    private GoodsLabelAssociateManager goodsLabelAssociateManager;

    @Autowired
    private PickGoodsSearchService pickGoodsSearchService;

    public long countByClassifyId(Integer classifyId) {
        GoodsExample example = new GoodsExample();
        example.createCriteria().andClassifyIdEqualTo(classifyId).andDeletedEqualTo(Goods.NOT_DELETED);
        return dao.countByExample(example);
    }

    public long countByBrandId(Integer brandId) {
        GoodsExample example = new GoodsExample();
        example.createCriteria().andBrandIdEqualTo(brandId).andDeletedEqualTo(Goods.NOT_DELETED);
        return dao.countByExample(example);
    }

    private void verify(EditGoodsDTO record) {
        BizAssert.isTrue(Check.notNullOrTrimEmpty(record.getName()), ResultCode.VERIFY.build(10), "商品名称不能为空");
        BizAssert.isTrue(Check.notNull(record.getBrandId()), ResultCode.VERIFY.build(10), "商品品牌不能为空");
    }

    @Transactional
    public GoodsWithBLOBs create(EditGoodsDTO add, String createUser) {
        verify(add);

        GoodsWithBLOBs record = new GoodsWithBLOBs();
        record.setName(add.getName());
        record.setBrandId(add.getBrandId());
        record.setClassifyId(add.getClassifyId());
        record.setLabelIds(Check.isNull(add.getLabelIds()) ? null : JSON.toJSONString(add.getLabelIds()));
        record.setCoded(add.getCoded());
        record.setBarCodes(Check.isNull(add.getBarCodes()) ? null : JSON.toJSONString(add.getBarCodes()));
        record.setUnit(add.getUnit());
        record.setCounterPrice(add.getCounterPrice());
        record.setRetailPrice(add.getRetailPrice());
        record.setCurrencyType(add.getCurrencyType());
        record.setImage(add.getImage());
        record.setShopwindowImages(Check.isNull(add.getShopwindowImages()) ? null : JSON.toJSONString(add.getShopwindowImages()));
        record.setDetail(add.getDetail());
        record.setParameters(Check.isNull(add.getParameters()) ? null : JSON.toJSONString(add.getParameters()));
        record.setAfterServiceId(add.getAfterServiceId());
        record.setStatus(GoodsStatus.ENABLE.real());
        record.setDeleted(Goods.NOT_DELETED);
        record.setCreateUser(createUser);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(createUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.insert(record);

        // 创建附件列表
        goodsAttachmentManager.create(record, createUser);
        // 刷新标签
        goodsLabelAssociateManager.refresh(record, createUser);
        return record;
    }

    @Transactional
    public void update(Integer goodsId, EditGoodsDTO edit, String updateUser) {
        verify(edit);
        // 获取一下旧数据
        Goods old = getById(goodsId);

        GoodsWithBLOBs record = new GoodsWithBLOBs();
        record.setGoodsId(goodsId);
        record.setName(edit.getName());
        record.setBrandId(edit.getBrandId());
        record.setClassifyId(edit.getClassifyId());
        record.setLabelIds(Check.isNull(edit.getLabelIds()) ? null : JSON.toJSONString(edit.getLabelIds()));
        record.setCoded(edit.getCoded());
        record.setBarCodes(Check.isNull(edit.getBarCodes()) ? null : JSON.toJSONString(edit.getBarCodes()));
        record.setUnit(edit.getUnit());
        record.setCounterPrice(edit.getCounterPrice());
        record.setRetailPrice(edit.getRetailPrice());
        record.setCurrencyType(edit.getCurrencyType());
        record.setImage(edit.getImage());
        record.setShopwindowImages(Check.isNull(edit.getShopwindowImages()) ? null : JSON.toJSONString(edit.getShopwindowImages()));
        record.setDetail(edit.getDetail());
        record.setParameters(Check.isNull(edit.getParameters()) ? null : JSON.toJSONString(edit.getParameters()));
        record.setAfterServiceId(edit.getAfterServiceId());
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        GoodsExample example = new GoodsExample();
        example.createCriteria().andGoodsIdEqualTo(goodsId).andDeletedEqualTo(Goods.NOT_DELETED);

        int row = dao.updateByExampleSelective(record,
                example,
                Column.name,
                Column.brandId,
                Column.classifyId,
                Column.labelIds,
                Column.coded,
                Column.barCodes,
                Column.unit,
                Column.counterPrice,
                Column.retailPrice,
                Column.currencyType,
                Column.image,
                Column.shopwindowImages,
                Column.detail,
                Column.parameters,
                Column.afterServiceId,
                Column.updateUser,
                Column.updateTime
        );

        BizAssert.isTrue(row == 1, "修改商品属性失败");
        // 刷新标签
        goodsLabelAssociateManager.refresh(record, updateUser);
        // 刷新缓存
        pickGoodsSearchService.changeGoods(old, edit);
    }

    @Transactional
    public void delete(GoodsWithBLOBs record, String updateUser) {
        // check
        long countPickGoodsUsedNumber = pickGoodsManager.countByGoodsId(record.getGoodsId());
        BizAssert.isTrue(countPickGoodsUsedNumber == 0,
                ResultCode.VERIFY.build(10),
                "该商品还有{}个优选商品使用",
                countPickGoodsUsedNumber);

        record.setDeleted(Goods.IS_DELETED);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        GoodsExample example = new GoodsExample();
        example.createCriteria()
                .andGoodsIdEqualTo(record.getGoodsId())
                .andDeletedEqualTo(Goods.NOT_DELETED);

        int row = dao.updateByExampleSelective(record, example,
                Column.deleted,
                Column.updateUser,
                Column.updateTime);

        BizAssert.isTrue(row == 1, "删除商品失败");

        // 删除附件
        goodsAttachmentManager.deleteByGoodsId(record.getGoodsId(), updateUser);
        // 删除标签
        goodsLabelAssociateManager.deleteByGoodsId(record.getGoodsId(), updateUser);
        // 删除规格
        goodsSpecGroupManager.deleteByGoodsId(record.getGoodsId(), updateUser);
        goodsSpecManager.deleteByGoodsId(record.getGoodsId(), updateUser);
        // 删除产品
        goodsProductManager.deleteByGoodsId(record.getGoodsId(), updateUser);
    }

    void refreshProductPrice(Integer goodsId) {
        dao.refreshProductPrice(goodsId);
    }

    public GoodsWithBLOBs getById(Integer goodsId) {
        return dao.selectByPrimaryKeyWithLogicalDelete(goodsId, GoodsWithBLOBs.NOT_DELETED);
    }

    public Pagination<GoodsWithBLOBs> query(QueryGoodsDTO query, Sorting[] sorts, Page page) {
        GoodsExample example = new GoodsExample();
        GoodsExample.Criteria criteria = example.createCriteria();

        if (Check.notNullOrTrimEmpty(query.getName())) {
            criteria.andNameLike('%' + query.getName() + '%');
        }
        criteria.andDeletedEqualTo(Goods.NOT_DELETED);

        example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());

        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExampleWithBLOBs(example));
    }

    public List<Goods> queryByDesignerProjectId(Integer designerProjectId) {
        return dao.queryByDesignerProjectId(designerProjectId);
    }
}